package org.oschina.handler.validator;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.oschina.Message;
import org.oschina.ResultUtil;
import org.oschina.bean.Result;
import org.oschina.handler.BaseAopHandler;
import org.oschina.handler.validator.annotation.Validate;
import org.oschina.handler.validator.annotation.ValidateField;
import org.oschina.helper.ApplicationHelper;
import org.oschina.util.ReflectUtil;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

/**
 * 验证注解处理类
 */
@Component
@Aspect
public class ValidateHandler extends BaseAopHandler implements Ordered {
	
	@Override
	public int getOrder()
	{
		return 10;
	}
	
	@Pointcut("@annotation(org.oschina.handler.validator.annotation.Validate)")
	public void aroundPoint(){};
	
	@Around(value="aroundPoint()")
	public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
	{
		Method method=getMethod(proceedingJoinPoint);
		Annotation argAnnotations[]=ReflectUtil.getAnnotationByMethodParameter(method, Validate.class);
		Class argTypes[]=method.getParameterTypes();
		Object args[]=proceedingJoinPoint.getArgs();
		
		boolean pass=true;
		for(int i=0,len=argAnnotations.length;i<len;i++)
		{
			Validate validate=(Validate)argAnnotations[i];
			if(validate==null)
				continue;
			
			ValidateField validateFields[]=validate.validateField();
			if(validateFields.length==0)
				continue;
			
			Class argType=argTypes[i];
			Object arg=args[i];
			
			//普通类型
			if(ReflectUtil.isBasic(argType))
			{
				Object newArg[]=new Object[]{arg};
				pass=validate(validateFields[0],argType,newArg);
				arg=newArg[0];
			}
			//数组类型
			else if(argType.getName().startsWith("["))
			{
				if(arg==null)
				{
					pass=false;
					break;
				}
				
				Object newArg[]=(Object[])arg;
				for(int j=0;j<newArg.length;j++)
				{
					Object tempValue[]=new Object[]{newArg[i]};
					pass=validate(validateFields[0],argType.getComponentType(),tempValue);
					
					if(!pass)
						break;
					
					newArg[i]=tempValue[0];
				}
				
				arg=newArg;
			}
			//其他类型
			else
			{
				if(arg==null)
				{
					pass=false;
					break;
				}
				
				for(ValidateField validateField:validateFields)
				{
					if(StringUtils.isBlank(validateField.name()))
						continue;
					
					Field field=argType.getDeclaredField(validateField.name());
					Object fieldValue[]=new Object[]{BeanUtils.getProperty(arg,validateField.name())};
					pass=validate(validateField,field.getType(),fieldValue);
					
					if(!pass)
						break;
					
					BeanUtils.setProperty(arg, validateField.name(), fieldValue[0]);
				}
			}
			
			args[i]=arg;
			
			if(!pass)
				break;
		}

		//验证不通过
		if(!pass)
		{
			if(method.getReturnType().equals(Result.class))
				return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
			else
				return null;
		}
		
		return proceedingJoinPoint.proceed(args);
	}
	
	/**
	 * 验证
	 * @param validateField
	 * @param type
	 * @param arg 保证对象引用传递
	 * @return
	 */
	private boolean validate(ValidateField validateField,Class type,Object arg[])
	{
		boolean pass=true;
		
		//是否需要验证
		if(!validateField.validate())
			return true;
		
		//判断必须为空
		if(validateField.mustNull())
		{
			arg[0]=null;
			return true;
		}
		
		//判断允许为空
		if(validateField.notNull() && arg[0]==null)
			return false;
		
		//执行过滤器
		String argStr=(arg[0]==null?null:arg[0].toString());
		if(type.equals(String.class))
		{
			ValidateBean validateBean=new ValidateBean(type,argStr);
			Class filters[]=validateField.filter();
			for(int j=0,jlen=filters.length;j<jlen;j++)
			{
				IFilter filter=getFilterInstance(filters[j]);
				if(filter!=null)
					filter.execute(validateBean);
			}
			arg[0]=validateBean.getValue();
			argStr=(arg[0]==null?null:arg[0].toString());
		}
		
		if(validateField.notNull())
		{
			if(StringUtils.isBlank(argStr))
				pass=false;
			else
			{
				//是否验证值
				if(validateField.validateValue())
				{
					if(type.equals(String.class))
					{
						if(argStr.length()<validateField.min() || (argStr.length()>validateField.max() && validateField.max()>=0))
							pass=false;
					}
					else if(type.equals(Long.class) || type.equals(Integer.class))
					{
						long value=Long.parseLong(argStr);
						if(value<validateField.min() || (value>validateField.max() && validateField.max()>=0))
							pass=false;
					}
					else if(type.getName().startsWith("["))
					{
						Object temp[]=(Object[])arg;
						if(temp.length<validateField.min() || (temp.length>validateField.max() && validateField.max()>=0))
							pass=false;
					}
				}
			}
		}

		return pass;
	}
	
	/**
	 * 返回过滤器实例
	 * @param clazz
	 * @return
	 */
	private IFilter getFilterInstance(Class clazz)
	{
		return (IFilter)ApplicationHelper.getBean(clazz);
	}
}